# -*- encoding: utf-8 -*-
"""
    package.module
    ~~~~~~~~~~~~~~

    Public function

    :copyright: (c)  2018/8/21 by zwhset.
    :license: OPS, see LICENSE_FILE for more details.
"""
import os
import time
from datetime import datetime
import requests

import redis, json

from flask import jsonify, request
from functools import wraps

from errors import HTTPError, JSONUnmarshalError, ParamsError, ENVError
from config import configure
from logs.log import logger


def utc_to_local(t):
    """UTC时间转本地时间（+8:00)"""
    now = time.time()
    local_stamp = t + (
        datetime.fromtimestamp(now) - datetime.utcfromtimestamp(now)
    )
    return local_stamp.strftime("%Y-%m-%d %H:%M:%S")


def http_json_request(url, method='POST', data={}, headers={}, cookies={}):
    """
    通用请求方法

    :param url:
    :param data: post data
    :param params: get data
    :param headers: request headers
    """
    if not url:
        raise ParamsError('not fund url params.')

    try:
        if method.upper() == 'POST':
            r = requests.post(url, data=data, headers=headers, cookies=cookies)
            logger.info(
                "http_json_request POST Request URL {0} data: {1} cookies: {2}".format(url, data, cookies))
        elif method.upper() == 'GET':
            logger.info(
                "http_json_request GET Request URL {0} data: {1}  cookies: {2}".format(url, data, cookies))
            r = requests.get(url, params=data, headers=headers, cookies=cookies)
        else:
            r = None
    except Exception as e:
        # logger
        logger.exception("http_json_request Request URL Fail, {0}".format(str(e)))
        raise HTTPError('请求URL错误, {0}'.format(url))

    try:
        res = r.json()
        logger.info(res)
        return res
    except Exception as e:
        # logger
        logger.exception("http_json_request JSON Unmarshal Fail, {0}".format(str(e)))
        raise JSONUnmarshalError('JSON解析出错, 信息: {0}'.format(str(e)))


def get_cookies(username='ops', passwd='qazQAZ2@'):
    """
    获得sso认证cookie
    :param username: LDAP用户名
    :param passwd: LDAP密码
    :return:
    """
    sso_url = configure.SSO_API + '/api/v1/sso'
    data = {'Username': username, 'Password': passwd}
    result = requests.post(sso_url, data=data)
    if result.status_code == 200:
        return result.cookies
    else:
        return {}


def env_esxit(env):
    """
    环境是否存在
    :param env:
    :return:
    """
    if env not in configure.PROJECT_ENVS:
        raise ENVError('ENV: {0} 不存在于 {1}'.format(
            env, configure.PROJECT_ENVS
        ))


def env_rules(f):
    """
    环境是否合法, 集群是否合法
    :param f: func
    :return:
    """

    @wraps(f)
    def wrapper(*args, **kwargs):
        env = request.view_args.get('env')
        try:
            env_esxit(env=env)
        except Exception as e:
            logger.exception(e)
            return jsonify(dict(
                code=5001,
                message=str(e)
            ))
        return f(*args, **kwargs)

    return wrapper


def check_cookie(cookies):
    """
    cookie验证
    :param cookies:
    :return:
    """
    sso_url = "http://sso.qianbao-inc.com/kycookie"
    response = requests.get(sso_url, params=dict(Qianbao_OPS=cookies))
    if response.content == 'Success':
        return True
    else:
        return False


def parse_cookie(sso_cookie):
    username = '-'
    if sso_cookie:
        if "Qianbao_OPS" in sso_cookie.keys():
            kcookie = sso_cookie["Qianbao_OPS"]
            username = kcookie.split('-')[1]
            return username
        else:
            return username
    else:
        return username


def parse_token(sso_cookie):
    username = ''
    if sso_cookie:
        username = sso_cookie.split('-')[1]
        return username
    else:
        return username


def api_user_chinese(user):
    data = {}
    sso_type_url = 'http://sso.qianbao-inc.com/api/v1/user_chinese'
    data["username"] = user
    req = requests.post(sso_type_url, data=data)
    if req:
        record = json.loads(req.content)
        if record["status"]:
            return record["result"]
        else:
            return user
    else:
        return user


class Redis(object):
    """Redis Object"""

    def __init__(self):
        self.client = None  # redis client
        self.__init()

    def __connect(self):
        """Connect Reids conn"""

        self.client = redis.StrictRedis(
            host=configure.REDIS_HOST,
            port=configure.REDIS_PORT,
            password=configure.REDIS_PASSWORD,
            db=configure.REDIS_DB
        )

    def __init(self):
        """init redis instance 重试三次"""
        try:
            self.__connect()
        except:
            try:
                self.__connect()
            except:
                self.__connect()


class RedisCache():
    """Redis Cache 中间缓存项"""

    def __init__(self, cluster_name=None, username=None, pm_name=None):
        self.cluster_name = cluster_name
        self.username = username
        self.pm_name = pm_name
        self.redis = Redis().client

        # 中间缓存Redis key
        self.PROJECT_INFO_KEY = 'Project:Info:{0}'
        self.PROJECT_ENV_KEY = 'Project:Env:{0}'
        self.PROJECT_USER_PM_ENV_KEY = 'Project:UserPmEnv:{username}:{pm_name}'
        self.PROJECT_USER_PM_PRODUCT = 'Project:UserPmProduct:{username}:{pm_name}'
        self.INFO_TYPE = 0
        self.ENV_TYPE = 1
        self.USER_ENV_TYPE = 2
        self.USER_PRODUCT_TYPE = 3

        self.CACHE_TTL = 180  # 缓存项目中心数据为180秒

    def gen_key(self, cache_type):
        """根据集群类型生成key"""
        if cache_type == self.INFO_TYPE:
            key = self.PROJECT_INFO_KEY.format(self.cluster_name)
        elif cache_type == self.ENV_TYPE:
            key = self.PROJECT_ENV_KEY.format(self.cluster_name)
        elif cache_type == self.USER_ENV_TYPE:
            key = self.PROJECT_USER_PM_ENV_KEY.format(username=self.username, pm_name=self.pm_name)
        elif cache_type == self.USER_PRODUCT_TYPE:
            key = self.PROJECT_USER_PM_PRODUCT.format(username=self.username, pm_name=self.pm_name)
        else:
            key = self.PROJECT_INFO_KEY.format(self.cluster_name)

        return key

    def get_cache(self, cache_type):
        """
        从Redis里获取信息

        :param cache_type:  缓存类型， 对应INFO_TYPE ENV_TYPE
        :return:
        """
        key = self.gen_key(cache_type)

        try:
            data = self.redis.get(key)
            if data:
                return json.loads(data)
            else:
                return None
        except:  # 否则所有的都走项目中心
            return None

    def set_cache(self, cache_type, data={}, ttl=180):
        """
       设置Redis信息

        :param cache_type:  缓存类型， 对应INFO_TYPE ENV_TYPE
        :param data: 存放在Redis的内容
        :return:
        """
        key = self.gen_key(cache_type)

        try:
            sts = self.redis.set(key, json.dumps(data), ex=ttl)
            return bool(sts)
        except:
            return False
